<?php

namespace App\Tables;

use App\Notifications\ResetPassword;
use Carbon\Carbon;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Laravel\Passport\HasApiTokens;
use Zizaco\Entrust\Traits\EntrustUserTrait;
use Illuminate\Support\Facades\Cache;
use Illuminate\Cache\TaggableStore;

use DB;
use Log;

class User extends Authenticatable
{
    use Notifiable, EntrustUserTrait, HasApiTokens;

    protected $table = 'users';

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name', 'type', 'email', 'identity_card', 'password', 'sex', 'is_effect',
        'source', 'nickname', 'realname', 'mobile', 'invite_code', 'wx_official_open_id', 'wx_union_id',
        'province_code', 'baidu_push_channel_id', 'city_code', 'district_code', 'address'
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token', 'province', 'city', 'district',
    ];

    protected $appends = [
        'source_text',
        'sex_text',
        'roles_text',
        'roles_name',
        'prorations',
        'full_address',
        'parent_path',
        'parent_id',
        'is_signed_in',
        'my_invite_code',
        'invite_give_score_num',
        'invite_user_status'
    ];

    /**
     * passport API用户登录认证字段
     * @param $username
     * @return mixed
     */
    public function findForPassport($username)
    {
        $pattern = "/^([0-9A-Za-z\\-_\\.]+)@([0-9a-z]+\\.[a-z]{2,3}(\\.[a-z]{2})?)$/i";
        $column_name = preg_match($pattern, $username) ? 'email' : 'name';

        $mobile_pattern = "/^1[0-9]{10}$/";
        $column_name = preg_match($mobile_pattern, $username) ? 'mobile' : $column_name;

        // 判断前后用户
        $params = app('request')->all();
        if (isset($params['backend']) && $params['backend'] === 'yes') {
            return $this->where($column_name, $username)->backend()->first();
        }

        return $this->where($column_name, $username)->general()->first();
    }

    /**
     * Send the password reset notification.
     *
     * @param  string  $token
     * @return void
     */
    public function sendPasswordResetNotification($token)
    {
        $this->notify(new ResetPassword($token));
    }

    /**
     * 限制查询普通用户。
     * @param $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeGeneral($query)
    {
        return $query->where('type', 0);
    }

    /**
     * 限制查询代理用户
     * @param $query
     * @return mixed
     */
    public function scopeAgents($query)
    {
        return $query->withRole('agent');
    }

    /**
     * 限制查询后台用户
     * @param $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeBackend($query)
    {
        return $query->where('type', 1);
    }

    /**
     * 获取用户注册来源文本
     * @return string
     */
    public function getSourceTextAttribute()
    {
        switch ($this->source) {
            case 'backend':
                return '后台添加';
            case 'web':
                return '网站注册';
            case 'weixin':
                return '微信注册';
            case 'alipay':
                return '支付宝注册';
            case 'ios':
                return 'IOS客户端';
            case 'android':
                return 'Android客户端';
            default:
                return '未知来源';
        }
    }

    /**
     * 获取用户性别文本
     * @return string
     */
    public function getSexTextAttribute()
    {
        switch ($this->sex) {
            case '0':
                return '保密';
            case '1':
                return '男';
            case '2':
                return '女';
            default:
                return '未知';
        }
    }

    /**
     * 获取用户角色文本
     * @return string
     */
    public function getRolesTextAttribute()
    {
        $roles = [];
        foreach ($this->roles as $role) {
            $roles[] = $role->display_name;
        }

        return implode(' | ', $roles);
    }

    /**
     * 获取用户角色Names
     * @return string
     */
    public function getRolesNameAttribute()
    {
        $roles = [];
        foreach ($this->roles as $role) {
            $roles[] = $role->name;
        }

        return $roles;
    }

    /**
     * 获取代理层级
     * @return string
     */
    public function getParentIdAttribute()
    {
        if ($this->hasRole('agent')) {
            if ($this->extension->agent_level > 1) {
                return $this->extension->parent->id;
            }
        }

        return 0;
    }

    /**
     * 获取代理层级
     * @return string
     */
    public function getParentPathAttribute()
    {
        $path = [];
        if ($this->hasRole('agent')) {
            if ($this->extension->agent_level == 1) {
                $path[] = '顶级代理';
            } else if ($this->extension->agent_level == 2) {
                $path[] = $this->extension->parent->realname;
            } else if ($this->extension->agent_level == 3) {
                $path[] = $this->extension->parent->extension->parent->realname;
                $path[] = $this->extension->parent->realname;
            }
        }

        return implode('/', $path);
    }

    /**
     * 获取代理分红配置信息
     * @return mixed
     */
    public function getProrationsAttribute()
    {
        if (empty($this->extension)) {
            return [];
        }
        return $this->extension->prorations;
    }

    /**
     * 获取代理分红配置信息
     * @return mixed
     */
    public function getProrationAttribute()
    {
        if (empty($this->extension)) {
            return 0;
        }
        return $this->extension->proration;
    }

    /**
     * 获取自己的邀请码
     * @return string
     */
    public function getMyInviteCodeAttribute()
    {
        if (!isset($this->mobile) || empty($this->mobile)) {
            return '';
        }

        return base_convert($this->mobile, 10, 32);
    }

    /**
     * 获取邀请新用户奖励积分数量
     * @return \Illuminate\Config\Repository|mixed
     */
    public function getInviteGiveScoreNumAttribute()
    {
        return config('system.user_invite.give_score_num', 0);
    }

    /**
     * 获取邀请新用户功能是否开启
     * @return \Illuminate\Config\Repository|mixed
     */
    public function getInviteUserStatusAttribute()
    {
        return config('system.user_invite.status', false);
    }

    /**
     * 获取省信息
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function province()
    {
        return $this->hasOne('App\Tables\Region', 'code', 'province_code');
    }

    /**
     * 获取城市信息
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function city()
    {
        return $this->hasOne('App\Tables\Region','code', 'city_code');
    }

    /**
     * 获取地区信息
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function district()
    {
        return $this->hasOne('App\Tables\Region', 'code', 'district_code');
    }

    /**
     * 获取完整的地址信息
     * @return string
     */
    public function getFullAddressAttribute()
    {
        $full_address = '';

        if (!empty($this->province)) {
            $full_address .= $this->province->name;
        }
        if (!empty($this->city)) {
            $full_address .= $this->city->name;
        }
        if (!empty($this->district)) {
            $full_address .= $this->district->name;
        }

        if (isset($this->attributes['address'])) {
            $full_address .= $this->attributes['address'];
        }
        return $full_address;
    }

    /**
     * 当前用户当天是否已经签到
     * @return bool
     */
    public function getIsSignedInAttribute()
    {
        /**
         * 判断今日是否已经签到过了
         * @param $user_id
         * @return bool
         */
        $has_signed_in_func = function ($user_id) {
            $today_score_records = UserScoreTransferRecord::where('user_id', $user_id)
                ->where('type', 'sign_in_give')
                ->whereDate('created_at', date('Y-m-d'))
                ->get();

            if ($today_score_records->isEmpty()) {
                return false;
            }
            return true;
        };

        $cacheKey = 'user_sign_in_' . $this->id . '_' . date('Ymd');
        if(Cache::getStore() instanceof TaggableStore) {
            return Cache::tags('user_sign_in')->remember($cacheKey, Carbon::now()->addHour(12), function () use ($has_signed_in_func) {
                return $has_signed_in_func($this->id);
            });
        }

        return $has_signed_in_func($this->id);
    }

    /**
     * 获取所有下级代理
     * @param $query
     * @param $id
     * @return mixed
     */
    public function scopeOfChildren($query, $id)
    {
        return $query->whereIn('id', function ($query) use ($id) {
            $query->select('ar.child_id as id')
                ->from('users as u')
                ->join('agent_relation as ar', 'u.id', '=', 'ar.parent_id')
                ->where(function ($query) use ($id) {
                    $query->orWhere('ar.parent_id', $id);
                    $query->orWhere('ar.child_id', $id);
                });
        });
    }

    /**
     * 获取用户扩展信息
     */
    public function extension()
    {
        return $this->belongsTo('App\Tables\UserAgentExtend', 'id', 'user_id');
    }
}
